package bnb

import (
	"context"
	"encoding/json"
	"errors"
	"log/slog"
	"raymond/global"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/tidwall/gjson"
)

const BscApiKey string = "ZNKB7JE3UX292YQ5SMXAAA4HFHHEKD1KYU"

type ListenBSCResult struct {
	Status  string
	Message string
	Result  []BSCTransaction
}

type BSCTransaction struct {
	BlockNumber       string
	TimeStamp         string
	Hash              string
	Nonce             string
	BlockHash         string
	From              string
	ContractAddress   string
	To                string
	Value             string
	TokenName         string
	TokenSymbol       string
	TokenDecimal      string
	TransactionIndex  string
	Gas               string
	GasPrice          string
	GasUsed           string
	CumulativeGasUsed string
	Input             string
	Confirmations     string
}

func ListenETH() {
	client := global.Client()

	headers := make(chan *types.Header)

	for {
		subscription, err := client.SubscribeNewHead(context.Background(), headers)
		if err != nil {
			slog.Error("", err)
		}
		select {
		case err := <-subscription.Err():
			slog.Error("", err)
		case header := <-headers:
			block, err := client.BlockByHash(context.Background(), header.Hash())
			if err != nil {
				slog.Error("", err)
				continue
			}

			for _, tx := range block.Transactions() {
				if tx.To() == nil {
					slog.Info("ListenETH", "New incoming transaction received", tx.Hash().Hex())
				}
			}
		}
	}
}

func ListenBSCBEP20(contractAddress string, address string) (*ListenBSCResult, error) {
	var listenUrl string = global.GetBSCApiUrl() + "/api?module=account&action=tokentx&contractaddress=" + contractAddress + "&address=" + address + "&page=1&offset=10&sort=desc&apikey=" + BscApiKey

	resultBytes, err := global.HttpGet(listenUrl)
	if err != nil {
		return nil, err
	}
	resultString := string(resultBytes)

	statusValue := gjson.Get(resultString, "status")
	if statusValue.String() == "0" {
		message := gjson.Get(resultString, "message")
		detailMessage := gjson.Get(resultString, "result")
		return nil, errors.New(message.String() + "_" + detailMessage.String())
	}
	var resp ListenBSCResult
	err = json.Unmarshal(resultBytes, &resp)
	if err != nil {
		slog.Error("unmarshal err", "result", resultString)
		return nil, err
	}
	return &resp, nil
}

func ListenBSCBEP721(contractAddress string, address string) (*ListenBSCResult, error) {
	var listenUrl string = global.BSC_TEST_API_URL + "/api?module=account&action=tokennfttx&contractaddress=" + contractAddress + "&address=" + address + "&page=1&offset=10&sort=desc&apikey=" + BscApiKey

	result, err := global.HttpGet(listenUrl)
	if err != nil {
		return nil, err
	}

	var resp ListenBSCResult
	err = json.Unmarshal(result, &resp)
	if err != nil {
		return nil, err
	}
	return &resp, nil
}
